package com.gkzf.ai.module.crm.util.simpleCredit;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.gkzf.ai.module.crm.controller.admin.simpleCredit.vo.*;
import com.gkzf.ai.module.crm.dal.dataobject.creditreportsimple.CreditReportSimpleCreditCardDO;
import com.gkzf.ai.module.crm.dal.dataobject.creditreportsimple.CreditReportSimpleLoanDO;
import com.gkzf.ai.module.crm.framework.annotations.utils.JsonParser;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

import static com.gkzf.ai.module.crm.util.AnalysisJsonObjectUtils.*;
import static com.gkzf.ai.module.crm.util.assembly.AssemblyCreditReportDetails.*;

/**
 * @author 简版征信数据提取
 * @date  2019/12/31 14:22
 */
@Slf4j
public class SimpleCreditExtract {


    /** 外层key字段名 */
    public static final String RESULT = "result";

    /** 报告时间字段名 */
    public static final String FIELD_NAME_REPORT_DATE = "报告时间";

    /** 姓名字段名 */
    public static final String FIELD_NAME_USER_NAME = "姓名";

    /** 证件号码字段名 */
    public static final String FIELD_NAME_ID_NUMBER = "证件号码";

    /** 婚姻状况字段名 */
    public static final String FIELD_NAME_MARITAL_STATUS = "婚姻状况";

    /** 欠税信息字段名 (指向 TaxArrears) */
    public static final String FIELD_NAME_TAX_ARREARS = "欠税信息";

    /** 民事判决信息字段名 (指向 CivilJudgments) */
    public static final String FIELD_NAME_CIVIL_JUDGMENTS = "民事判决信息";

    /** 强制执行信息字段名 (指向 Enforcement) */
    public static final String FIELD_NAME_ENFORCEMENT = "强制执行信息";

    /** 行政处罚信息字段名 (指向 AdministrativePenalties) */
    public static final String FIELD_NAME_ADMINISTRATIVE_PENALTIES = "行政处罚信息";

    /** 公共信息汇总信息记录数字段名 */
    public static final String FIELD_NAME_RECORD_COUNT = "记录数";

    /** 公共信息汇总涉及金额字段名 */
    public static final String FIELD_NAME_AMOUNT = "涉及金额";

    /** 本人查询日期字段名 */
    public static final String FIELD_NAME_DATE = "查询日期";

    /** 本人查询原因字段名 */
    public static final String REASON = "查询原因";

    /** 本人查询机构字段名 */
    public static final String QUERY_INSTITUTION = "查询机构";

    /** 信用卡字段名 (指向 CreditInfoItem) */
    public static final String FIELD_NAME_CREDIT_CARD = "信用卡";

    /** 信用卡字段名 (指向 CreditInfoItem) */
    public static final String OVERDUE_CREDIT_CARD_ACCOUNTS = "发生过逾期的贷记卡账户明细";

    /** 信用卡字段名 (指向 CreditInfoItem) */
    public static final String NON_OVERDUE_CREDIT_CARD_ACCOUNTS = "从未逾期过的贷记卡及透支未超过60天的准贷记卡账户明细";

    /** 贷款字段名 (指向 LoanInfo) */
    public static final String FIELD_NAME_LOAN = "贷款";

    /** 其他业务字段名 (指向 LoanInfo) */
    public static final String OTHER_BUSINESSES = "其他业务";


    /** 其他业务从未逾期过的账户明细字段名 (指向 LoanInfo) */
    public static final String OTHER_NEVER_OVERDUE_ACCOUNTS = "从未逾期过的账户明细";

    /** 其他业务从未逾期过的账户明细字段名 (指向 LoanInfo) */
    public static final String OTHER_OVERDUE_ACCOUNTS = "发生过逾期的账户明细";

    /** 贷款逾期账户字段名 (指向 loan) */
    public static final String OVERDUE_ACCOUNTS = "发生过逾期的账户明细(贷款)";

    /** 贷款未逾期账户字段名 (指向 loan) */
    public static final String NEVER_OVERDUE_ACCOUNTS = "从未发生过逾期的账户(贷款)";

    /** 基本信息字段名 (指向 BasicInfo) */
    public static final String FIELD_NAME_BASIC_INFO = "基本信息";

    /** 机构查询记录明细字段名 (指向 List<PersonalInquiryItem>) */
    public static final String FIELD_NAME_PERSONAL_INQUIRIES = "机构查询记录明细";

    /** 个人查询记录明细字段名 (指向 List<PersonalInquiryItem>) */
    public static final String FIELD_NAME_INSTITUTIONAL_INQUIRIES = "个人查询记录明细";

    /** 公共记录字段名 (指向 PublicRecords) */
    public static final String FIELD_NAME_PUBLIC_RECORDS = "公共记录";

    // 定义日期格式化器，可以处理 "yyyy-MM-dd" 和 "yyyy.MM.dd"
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("[yyyy-MM-dd HH:mm:ss][yyyy年MM月dd日]");

    private static final String STATUS_CLEARED = "已结清";


    // 支持的日期格式列表（按优先级排列）
    private static final List<DateTimeFormatter> INPUT_FORMATTERS = Arrays.asList(
            DateTimeFormatter.ofPattern("yyyy年M月d日"),     // 2025年5月7日
            DateTimeFormatter.ofPattern("yyyy年MM月dd日"),   // 2025年05月07日
            DateTimeFormatter.ofPattern("yyyy/MM/dd"),      // 2025/05/07
            DateTimeFormatter.ofPattern("yyyy.MM.dd"),      // 2025/05/07
            DateTimeFormatter.ofPattern("yyyy.M.d"),      // 2025/05/07
            DateTimeFormatter.ofPattern("yyyy-MM-dd"),      // 2025-05-07
            DateTimeFormatter.ofPattern("yyyy-M-d"),      // 2025-05-07
            DateTimeFormatter.ofPattern("yyyyMMdd")         // 20250507
    );

    // 定义日期格式："2025年5月7日"
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");




    @SneakyThrows
    public static void main(String[] args) {
        Map<String,Object> createReqVO = new HashMap<>();
        createReqVO.put(KEY_MODEL_LOAN, Files.readString(Paths.get("/Users/mac/Documents/2.txt")));
        createReqVO.put(KEY_MODEL_CREDIT_CARD, Files.readString(Paths.get("/Users/mac/Documents/3.txt")));
        createReqVO.put(KEY_QUERY_RECORD, Files.readString(Paths.get("/Users/mac/Documents/4.txt")));
        createReqVO.put(KEY_BASIC, Files.readString(Paths.get("/Users/mac/Documents/1.txt")));
        List<Map<String, String>> queryRecordList = new ArrayList<>();
        CreditReportSimpleSaveReqVO simpleSaveReqVO = new CreditReportSimpleSaveReqVO();
        AtomicInteger atomicInteger = new AtomicInteger(0);
        conversion(createReqVO,KEY_BASIC,loanInfo ->{
            extract(loanInfo,atomicInteger,simpleSaveReqVO,queryRecordList,new ArrayList<>(),new ArrayList<>());
            log.info("{}",loanInfo);
        });
        AtomicInteger barefoot = new AtomicInteger();
        conversion(createReqVO,KEY_QUERY_RECORD,loanInfo ->{

            extract(loanInfo,atomicInteger,simpleSaveReqVO,queryRecordList,new ArrayList<>(),new ArrayList<>());
            log.info("{}",loanInfo);
        });
        conversion(createReqVO,KEY_MODEL_CREDIT_CARD,loanInfo ->{
            extract(loanInfo,atomicInteger,simpleSaveReqVO,queryRecordList,new ArrayList<>(),new ArrayList<>());
            log.info("{}",loanInfo);
        });
        conversion(createReqVO,KEY_MODEL_LOAN,loanInfo ->{
            extract(loanInfo,atomicInteger,simpleSaveReqVO,queryRecordList,new ArrayList<>(), new ArrayList<>());
            log.info("{}",loanInfo);
        });
        // 取值：贷款余额➕信用卡已使用额度
        simpleSaveReqVO.setTotalLiabilities(simpleSaveReqVO.getLoanBalance().add(simpleSaveReqVO.getCreditCardUsedCredit()));
        log.info("{}",createReqVO);
    }


    /**
     * 将外层包裹的格式统一解析出来 只保留具体对象对应的key
     *
     * @param paramMap    完成的map
     * @param paramMapKey 外层包裹的key
     * @param parenMap    函数 提取出来的具体对象的map
     */
    public static void conversion(Map<String, Object> paramMap, String paramMapKey, Consumer<Map<String, Object>> parenMap) {
        Object object = paramMap.get(paramMapKey);
        if (Objects.nonNull(object) && object instanceof String str) {
            Map<String, Object> pojoMap = JSON.parseObject(str, new TypeReference<>() {
            });
            if (pojoMap.containsKey(RESULT)) {
                Map<String, Object> result = JSON.parseObject(pojoMap.get(RESULT).toString(), new TypeReference<>() {});
                parenMap.accept(result);
            }
        }
    }

    /**
     * 提取数据
     * @param paramMap 存储的map
     * @param atomicInteger 记录白户
     * @param simpleSaveReqVO 简版征信对象
     * @param queryRecordList 查询记录集合
     * @param simpleCreditCardList 简版征信信用卡集合
     * @param simpleLoanList 简版征信贷款集合
     */
    public static void extract(Map<String,Object> paramMap,
                               AtomicInteger atomicInteger,
                               CreditReportSimpleSaveReqVO simpleSaveReqVO,
                               List<Map<String, String>> queryRecordList,
                               List<CreditReportSimpleCreditCardDO> simpleCreditCardList,
                               List<CreditReportSimpleLoanDO> simpleLoanList){
        /*
            基本信息字段名 (指向 basic_info)
         */
        if (paramMap.containsKey(FIELD_NAME_BASIC_INFO)) {
            JSONObject jsonObject = getJSONObjectByKey(paramMap, FIELD_NAME_BASIC_INFO);
            // 姓名
            accumulate(simpleSaveReqVO, FIELD_NAME_USER_NAME, jsonObject, String::toString, CreditReportSimpleSaveReqVO::setName);
            // 婚姻状况
            accumulate(simpleSaveReqVO, FIELD_NAME_MARITAL_STATUS, jsonObject, String::toString, CreditReportSimpleSaveReqVO::setMarriageStatus);
            // 身份证号
            accumulate(simpleSaveReqVO, FIELD_NAME_ID_NUMBER, jsonObject, String::toString, CreditReportSimpleSaveReqVO::setIdNumber);
            // 征信报告时间
            accumulate(simpleSaveReqVO, FIELD_NAME_REPORT_DATE, jsonObject, String::toString, CreditReportSimpleSaveReqVO::setReportTime);
            // 性别
            if (StringUtils.isNotBlank(simpleSaveReqVO.getIdNumber())) {
                simpleSaveReqVO.setGender(getGender(simpleSaveReqVO.getIdNumber()));
            }
            // 性别
            if (StringUtils.isNotBlank(simpleSaveReqVO.getIdNumber())) {
                simpleSaveReqVO.setAge(getAge(simpleSaveReqVO.getIdNumber()));
            }
        }
        /*
            公共信息汇总 字段名 (指向 public_records)
         */
        if (paramMap.containsKey(FIELD_NAME_PUBLIC_RECORDS)) {
            JSONObject jsonObject = getJSONObjectByKey(paramMap, FIELD_NAME_PUBLIC_RECORDS);
            Map<String,Object> publicRecordsMap = JSON.parseObject(jsonObject.toJSONString(),new TypeReference<>(){});
            // 欠款信息
            JSONObject taxArrears = getJSONObjectByKey(publicRecordsMap, FIELD_NAME_TAX_ARREARS);
            accumulate(simpleSaveReqVO, FIELD_NAME_TAX_ARREARS+FIELD_NAME_RECORD_COUNT, taxArrears, Integer::parseInt, CreditReportSimpleSaveReqVO::setDebtInfoCount);
            accumulate(simpleSaveReqVO, FIELD_NAME_TAX_ARREARS+FIELD_NAME_AMOUNT, taxArrears,  BigDecimal::new, CreditReportSimpleSaveReqVO::setDebtInfoMoney);
            // 民生判断信息
            JSONObject civilJudgments = getJSONObjectByKey(publicRecordsMap, FIELD_NAME_CIVIL_JUDGMENTS);
            accumulate(simpleSaveReqVO, FIELD_NAME_CIVIL_JUDGMENTS+FIELD_NAME_RECORD_COUNT, civilJudgments, Integer::parseInt, CreditReportSimpleSaveReqVO::setCivilJudgmentInfoCount);
            accumulate(simpleSaveReqVO, FIELD_NAME_CIVIL_JUDGMENTS+FIELD_NAME_AMOUNT, civilJudgments,  BigDecimal::new, CreditReportSimpleSaveReqVO::setCivilJudgmentInfoMoney);
            // 强制执行信息
            JSONObject enforcement = getJSONObjectByKey(publicRecordsMap, FIELD_NAME_ENFORCEMENT);
            accumulate(simpleSaveReqVO, FIELD_NAME_ENFORCEMENT+FIELD_NAME_RECORD_COUNT, enforcement, Integer::parseInt, CreditReportSimpleSaveReqVO::setEnforceInfoCount);
            accumulate(simpleSaveReqVO, FIELD_NAME_ENFORCEMENT+FIELD_NAME_AMOUNT, enforcement,  BigDecimal::new, CreditReportSimpleSaveReqVO::setEnforceInfoMoney);
            // 行政处罚信息
            JSONObject administrativePenalties = getJSONObjectByKey(publicRecordsMap, FIELD_NAME_ADMINISTRATIVE_PENALTIES);
            accumulate(simpleSaveReqVO, FIELD_NAME_ADMINISTRATIVE_PENALTIES+FIELD_NAME_RECORD_COUNT, administrativePenalties, Integer::parseInt, CreditReportSimpleSaveReqVO::setExecutivePenalizeInfoCount);
            accumulate(simpleSaveReqVO, FIELD_NAME_ADMINISTRATIVE_PENALTIES+FIELD_NAME_AMOUNT, administrativePenalties,  BigDecimal::new, CreditReportSimpleSaveReqVO::setExecutivePenalizeInfoMoney);
        }
        /*
            机构查询记录 字段名 (指向 personal_inquiries)
         */
        if (paramMap.containsKey(FIELD_NAME_PERSONAL_INQUIRIES)) {
            JSONArray jsonArray = getJSONArrayByKey(paramMap, FIELD_NAME_PERSONAL_INQUIRIES);
            queryRecordList.addAll(JSON_TO_RECORD_MAP.apply(jsonArray,SELF));
        }
         /*
            个人查询记录 字段名 (指向 personal_inquiries)
         */
        if (paramMap.containsKey(FIELD_NAME_INSTITUTIONAL_INQUIRIES)) {
            JSONArray jsonArray = getJSONArrayByKey(paramMap, FIELD_NAME_INSTITUTIONAL_INQUIRIES);
            queryRecordList.addAll(JSON_TO_RECORD_MAP.apply(jsonArray,INSTITUTION));
        }
        /*
            信用卡账户明细列表
         */
        if (paramMap.containsKey(FIELD_NAME_CREDIT_CARD)) {
            JSONObject jsonObject = getJSONObjectByKey(paramMap, FIELD_NAME_CREDIT_CARD);
            // 未逾期信用卡账户明细列表
            JSONArray nonOverdueCreditCardAccounts = getJSONArrayByKey(jsonObject, NON_OVERDUE_CREDIT_CARD_ACCOUNTS);
            List<NonOverdueCreditCardAccount> nonOverdueCreditCardAccountList = JsonParser.parseArray(nonOverdueCreditCardAccounts, NonOverdueCreditCardAccount.class).stream().filter(item -> item.getAccountCurrency().equals("人民币")).toList();
            // 逾期信用卡账户明细列表
            JSONArray overdueCreditCardAccounts = getJSONArrayByKey(jsonObject,OVERDUE_CREDIT_CARD_ACCOUNTS);
            List<OverdueCreditCardAccount> overdueCreditCardAccountList = JsonParser.parseArray(overdueCreditCardAccounts, OverdueCreditCardAccount.class).stream().filter(item -> item.getAccountCurrency().equals("人民币")).toList();
            simpleCreditCardList.addAll(CREDIT_CARD_OVERDUE_CONVERT.apply(overdueCreditCardAccountList));
            simpleCreditCardList.addAll(CREDIT_CARD_CONVERT.apply(nonOverdueCreditCardAccountList));


            /*
               大白户：贷款排除结清的账户状态，其他账户的数量为0
             */
            int creditInvisible = AccountUtils.countAccountsByPredicate(nonOverdueCreditCardAccountList, overdueCreditCardAccountList, SimpleCreditExtract::creditInvisible, SimpleCreditExtract::creditInvisible);
            if (creditInvisible > 0) {
                atomicInteger.set(0);
            }
            /*
                2年内（账户的开立日期 - 报告时间），所有账户（信用卡+贷款）开立时间距报告时间＜6个月 或 2年外、5年内（账户的开立日期 - 报告时间），所有账户（信用卡+贷款）的账户状态为结清
             */
            else if (atomicInteger.get() != 0 && checkAccountOpeningDateAndStatus(nonOverdueCreditCardAccountList, simpleSaveReqVO.getReportTime()) && checkAccountOpeningDateAndStatus(overdueCreditCardAccountList, simpleSaveReqVO.getReportTime())) {
                atomicInteger.set(1);
            }else {
                atomicInteger.set(0);
            }

            /*
             计算信用汇总信息
                账户数：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活）
                授信总额：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活），账户信用额度总和
                已使用额度：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活），账户已用额度总和
                使用率：不可以编辑；取值：已使用额度➗授信总额
             */
            /*
                账户数：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活）
             */
            // 信用卡账户数
            int creditCardAccountCount = AccountUtils.countAccountsByPredicate(nonOverdueCreditCardAccountList,overdueCreditCardAccountList,SimpleCreditExtract::accountStatus,SimpleCreditExtract::accountStatus);
            // 账户数
            simpleSaveReqVO.setCreditCardAccountCount(creditCardAccountCount);

            // 汇总信用卡 信用卡逾期账户数
            simpleSaveReqVO.setOverdueCardAccount(overdueCreditCardAccountList.size());
            // 汇总逾期90天以上账户数
            int overdue90AccountCount = AccountUtils.countAccountsByPredicate(overdueCreditCardAccountList, SimpleCreditExtract::overdue90Account);
            simpleSaveReqVO.setOverdueCard90Account(overdue90AccountCount);
            /*
                逾期加上未逾期 总的 授信总额：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活），账户信用额度总和
             */
            BigDecimal creditCardGrossAmount = AccountUtils.countAccountsByPredicate(nonOverdueCreditCardAccountList,SimpleCreditExtract::accountStatus,NonOverdueCreditCardAccount::getCreditLimit,
                    overdueCreditCardAccountList,SimpleCreditExtract::accountStatus,OverdueCreditCardAccount::getCreditLimit);
            // 授信总额
            simpleSaveReqVO.setCreditCardGrossAmount(creditCardGrossAmount);

            // 逾期信用卡授信总额
            BigDecimal creditCardOverdueGrossAmount = AccountUtils.countAccountsByPredicate(overdueCreditCardAccountList,SimpleCreditExtract::accountStatus,OverdueCreditCardAccount::getCreditLimit);

            /*
                已使用额度：可编辑；取值：所有信用卡账户数量汇总（减去销户、尚未激活），账户已用额度总和
             */

            // 未逾期已使用额度
            BigDecimal creditCardUsedCredit = AccountUtils.countAccountsByPredicate(nonOverdueCreditCardAccountList,SimpleCreditExtract::accountStatus,NonOverdueCreditCardAccount::getUsedLimit);


            // 逾期信用卡余额  逾期信用卡 没有已用额度 需要 总额减去余额
            BigDecimal creditCardOverdueBalance = AccountUtils.countAccountsByPredicate(overdueCreditCardAccountList,SimpleCreditExtract::accountStatus,OverdueCreditCardAccount::getBalance);
            // 逾期信用卡已使用额度
            BigDecimal creditCardOverdueUsedCredit = creditCardOverdueGrossAmount.subtract(creditCardOverdueBalance);
            // 已使用额度
            simpleSaveReqVO.setCreditCardUsedCredit(creditCardUsedCredit.add(creditCardOverdueUsedCredit));
            // 未逾期信用卡授信余额  计算 授信总额(逾期+未逾期) - 逾期总额 - 未逾期已用额度 = 未逾期余额
            BigDecimal creditCardBalance = creditCardGrossAmount.subtract(creditCardOverdueGrossAmount).subtract(creditCardUsedCredit);
            // 累加逾期
            simpleSaveReqVO.setCreditCardBalance(creditCardBalance.add(creditCardOverdueBalance));
            // 使用率
            BigDecimal creditCardUsageRate = ratio().apply(simpleSaveReqVO.getCreditCardUsedCredit(), creditCardGrossAmount);
            simpleSaveReqVO.setCreditCardCurrentRate(creditCardUsageRate);

        }
        /*
            贷款明细
         */
        if (paramMap.containsKey(FIELD_NAME_LOAN)) {
            JSONObject jsonObject = getJSONObjectByKey(paramMap, FIELD_NAME_LOAN);
            // 未逾期信用卡账户明细列表
            JSONArray overdueLoanAccounts = getJSONArrayByKey(jsonObject, NEVER_OVERDUE_ACCOUNTS);
            List<NeverOverdueLoanAccount> nonOverdueLoanAccountList = JsonParser.parseArray(overdueLoanAccounts, NeverOverdueLoanAccount.class);
            // 逾期信用卡账户明细列表
            JSONArray nonOverdueLoanAccounts = getJSONArrayByKey(jsonObject, OVERDUE_ACCOUNTS);
            List<OverdueAccount> overdueLoanAccountList = JsonParser.parseArray(nonOverdueLoanAccounts, OverdueAccount.class);
            simpleLoanList.addAll(LOAN_OVERDUE_CONVERT.apply(overdueLoanAccountList));
            simpleLoanList.addAll(LOAN_CONVERT.apply(nonOverdueLoanAccountList));

            extracted(atomicInteger, simpleSaveReqVO, nonOverdueLoanAccountList, overdueLoanAccountList);


            /*
               贷款业务概要（未结清）
                ● 账户数：取值信息概要贷款-购房-未结清/未销户账户包括个人住房贷款，个人商用房（包括商住两用）贷款和个人住房公积金贷款账户数；余额：账户数内余额总和
                ● 车辆按揭：取值：账户数：取值信息概要贷款-购房-未结清/未销户账户数个人汽车消费贷款；余额：账户数内余额总和
                ● 银行机构：取值：所有贷款账户中、减去账户状态为“结清”
                ● 非银行机构：；取值：所有贷款账户中、减去账户状态为“结清”
             */
            // 住房按揭未结清 业务种类包括 个人住房商业贷款，个⼈住房公积⾦贷款
            int loanHousingMortgageNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName,SimpleCreditExtract::loanHousingMortgage,SimpleCreditExtract::loanHousingMortgage);
            BigDecimal loanHousingMortgageMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::loanHousingMortgage,NeverOverdueLoanAccount::getBalance,
                    overdueLoanAccountList,SimpleCreditExtract::loanHousingMortgage,OverdueAccount::getBalance);
            simpleSaveReqVO.setHousingMortgageAccount(loanHousingMortgageNumber);
            simpleSaveReqVO.setHousingMortgageMoney(loanHousingMortgageMoney);

            // 未结清 并且 业务种类值包括 个人汽车消费贷款
            int loanAutomobileNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::loanAutomobile,SimpleCreditExtract::loanAutomobile);
            BigDecimal loanAutomobileMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::loanAutomobile,NeverOverdueLoanAccount::getBalance,
                    overdueLoanAccountList,SimpleCreditExtract::loanAutomobile,OverdueAccount::getBalance);
            simpleSaveReqVO.setVehicleAccount(loanAutomobileNumber);
            simpleSaveReqVO.setVehicleMoney(loanAutomobileMoney);

            // 银行贷款判断条件
            int loanBankNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::loanBank,SimpleCreditExtract::loanBank);
            BigDecimal loanBankMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::loanBank,NeverOverdueLoanAccount::getBalance,
                    overdueLoanAccountList,SimpleCreditExtract::loanBank,OverdueAccount::getBalance);
            simpleSaveReqVO.setBankingOrganizationAccount(loanBankNumber);
            simpleSaveReqVO.setBankingOrganizationMoney(loanBankMoney);

            // 非银行贷款判断条件
            int nonLoanBankNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::loanAutomobile,SimpleCreditExtract::nonLoanBank);
            BigDecimal nonLoanBankMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::nonLoanBank,NeverOverdueLoanAccount::getBalance,
                    overdueLoanAccountList,SimpleCreditExtract::nonLoanBank,OverdueAccount::getBalance);
            simpleSaveReqVO.setNonBankingOrganizationAccount(nonLoanBankNumber);
            simpleSaveReqVO.setNonBankingOrganizationMoney(nonLoanBankMoney);


            // 消费性贷款判断条件
            int consumerLoanAccountNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::consumerLoan,SimpleCreditExtract::consumerLoan);
            BigDecimal consumerLoanMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::consumerLoan,NeverOverdueLoanAccount::getBalance,overdueLoanAccountList,SimpleCreditExtract::consumerLoan,OverdueAccount::getBalance);
            simpleSaveReqVO.setConsumerLoanAccount(consumerLoanAccountNumber);
            simpleSaveReqVO.setConsumerLoanMoney(consumerLoanMoney);


            // 经营性贷款判断条件
            int operateLoanAccountNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::operateLoan,SimpleCreditExtract::operateLoan);
            BigDecimal operateLoanMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::operateLoan,NeverOverdueLoanAccount::getBalance,overdueLoanAccountList,SimpleCreditExtract::operateLoan,OverdueAccount::getBalance);
            simpleSaveReqVO.setOperateLoanAccount(operateLoanAccountNumber);
            simpleSaveReqVO.setOperateLoanMoney(operateLoanMoney);


            // 小额贷款判断条件
            int pettyLoanAccountNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::pettyLoan,SimpleCreditExtract::pettyLoan);
            BigDecimal pettyLoanMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::pettyLoan,NeverOverdueLoanAccount::getBalance,overdueLoanAccountList,SimpleCreditExtract::pettyLoan,OverdueAccount::getBalance);
            simpleSaveReqVO.setPettyLoanAccount(pettyLoanAccountNumber);
            simpleSaveReqVO.setPettyLoanMoney(pettyLoanMoney);


            // 消费金融贷款判断条件
            int financeLoanAccountNumber = AccountUtils.countAccountsByPredicateRepeat(nonOverdueLoanAccountList,overdueLoanAccountList,NeverOverdueLoanAccount::getInstitutionName,OverdueAccount::getInstitutionName, SimpleCreditExtract::financeLoan,SimpleCreditExtract::financeLoan);
            BigDecimal financeLoanMoney = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::financeLoan,NeverOverdueLoanAccount::getBalance,overdueLoanAccountList,SimpleCreditExtract::financeLoan,OverdueAccount::getBalance);
            simpleSaveReqVO.setFinanceLoanAccount(financeLoanAccountNumber);
            simpleSaveReqVO.setFinanceLoanMoney(financeLoanMoney);
        } /*
            其他业务贷款明细
         */
        if (paramMap.containsKey(OTHER_BUSINESSES)) {
            JSONObject jsonObject = getJSONObjectByKey(paramMap, OTHER_BUSINESSES);
            // 未逾期信用卡账户明细列表
            JSONArray nonOverdueLoanAccounts = getJSONArrayByKey(jsonObject, OTHER_NEVER_OVERDUE_ACCOUNTS);
            List<NeverOverdueLoanAccount> nonOverdueLoanAccountList = JsonParser.parseArray(nonOverdueLoanAccounts, NeverOverdueLoanAccount.class);
            JSONArray overdueLoanAccounts = getJSONArrayByKey(jsonObject, OTHER_OVERDUE_ACCOUNTS);
            List<OverdueAccount> overdueLoanAccountList = JsonParser.parseArray(overdueLoanAccounts, OverdueAccount.class);
            extracted(atomicInteger, simpleSaveReqVO, nonOverdueLoanAccountList, overdueLoanAccountList);
        }

    }

    /**
     * 计算概要 贷款账户数、贷款授信总额，贷款余额
     * @param atomicInteger 计数器 用于记录白户
     * @param simpleSaveReqVO 简版征信报告保存参数
     * @param nonOverdueLoanAccountList 未逾期贷款账户列表
     * @param overdueLoanAccountList 逾期贷款账户列表
     */
    private static void extracted(AtomicInteger atomicInteger, CreditReportSimpleSaveReqVO simpleSaveReqVO, List<NeverOverdueLoanAccount> nonOverdueLoanAccountList, List<OverdueAccount> overdueLoanAccountList) {
    /*
        负债汇总 （贷款）
            账户数：可编辑；取值：所有贷款账户数量汇总（减去未结清）
            授信总额：可编辑；取值：所有贷款账户数量汇总（减去未结清），账户发放金额总和
            余额：可编辑；取值：所有贷款账户数量汇总（减去未结清），账户余额总
     */
        int loanAccountCount = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList, overdueLoanAccountList, SimpleCreditExtract::loanAccountStatus,SimpleCreditExtract::loanAccountStatus);
        // 逾期账户数
        int loanOverdueAccountCount = overdueLoanAccountList.size();
        // 账户数 (贷款)
        accumulateSup(simpleSaveReqVO, loanAccountCount, CreditReportSimpleSaveReqVO::getLoanAccountCount, CreditReportSimpleSaveReqVO::setLoanAccountCount);
        // 汇总贷款逾期账户数
        accumulateSup(simpleSaveReqVO, loanOverdueAccountCount, CreditReportSimpleSaveReqVO::getOverdueLoanAccount, CreditReportSimpleSaveReqVO::setOverdueLoanAccount);
        // 汇总逾期90天以上账户数
        int overdue90AccountCount = AccountUtils.countAccountsByPredicate(overdueLoanAccountList, SimpleCreditExtract::overdue90Account);
        accumulateSup(simpleSaveReqVO, overdue90AccountCount, CreditReportSimpleSaveReqVO::getOverdueLoan90Account, CreditReportSimpleSaveReqVO::setOverdueLoan90Account);
            /*
                贷款授信总额
             */
        BigDecimal loanGrossAmount = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::loanAccountStatus,NeverOverdueLoanAccount::getLoanAmount,
                overdueLoanAccountList,SimpleCreditExtract::loanAccountStatus,OverdueAccount::getLoanAmount);
        //授信总额 (贷款)
        accumulateSup(simpleSaveReqVO, loanGrossAmount, CreditReportSimpleSaveReqVO::getLoanGrossAmount, CreditReportSimpleSaveReqVO::setLoanGrossAmount);

            /*
               贷款余额
             */

        BigDecimal loanBalance = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList,SimpleCreditExtract::loanAccountStatus,NeverOverdueLoanAccount::getBalance,
                overdueLoanAccountList,SimpleCreditExtract::loanAccountStatus,OverdueAccount::getBalance);
        //余额
        accumulateSup(simpleSaveReqVO, loanBalance, CreditReportSimpleSaveReqVO::getLoanBalance, CreditReportSimpleSaveReqVO::setLoanBalance);


            /*
               大白户：贷款排除结清的账户状态，其他账户的数量为0
             */
        int creditInvisible = AccountUtils.countAccountsByPredicate(nonOverdueLoanAccountList, overdueLoanAccountList, SimpleCreditExtract::creditInvisible, SimpleCreditExtract::creditInvisible);
        if (creditInvisible > 0) {
            atomicInteger.set(0);
        }
        /*
            2年内（账户的开立日期 - 报告时间），所有账户（信用卡+贷款）开立时间距报告时间＜6个月 或 2年外、5年内（账户的开立日期 - 报告时间），所有账户（信用卡+贷款）的账户状态为结清
         */
        else if (atomicInteger.get() != 0 && checkAccountOpeningDateAndStatus(nonOverdueLoanAccountList, simpleSaveReqVO.getReportTime()) && checkAccountOpeningDateAndStatus(overdueLoanAccountList, simpleSaveReqVO.getReportTime())) {
            atomicInteger.set(1);
        }else {
            atomicInteger.set(0);
        }
    }

    /**
     * 查询记录转换
     */
    public static final BiFunction<JSONArray,String,List<Map<String,String>>> JSON_TO_RECORD_MAP = (jsonArray,self) -> {
        List<Map<String,String>> queryRecordList = new ArrayList<>();
        for (Object o : jsonArray) {
            JSONObject object = (JSONObject) o;
            Map<String, String> queryRecordMap = new LinkedHashMap<>();
            Object date = object.get(FIELD_NAME_DATE);
            Object reason = object.get(REASON);
            queryRecordMap.put(FIELD_NAME_DATE, DateUtil.format(DateUtil.parse(date.toString()), DatePattern.NORM_DATE_PATTERN));
            queryRecordMap.put(REASON, Optional.ofNullable(reason).orElse("").toString());
            queryRecordMap.put(QUERY_INSTITUTION, self);
            queryRecordList.add(queryRecordMap);
        }
        return queryRecordList;
    };


    public static JSONObject getJSONObjectByKey(Map<String, Object> paramMap,String key){
        Object object = paramMap.get(key);
        if (object instanceof JSONObject jsonObject) {
            return jsonObject;
        }
        return new JSONObject();
    }

    public static JSONArray getJSONArrayByKey(Map<String, Object> paramMap, String key){
        Object object = paramMap.get(key);
        if (object instanceof JSONArray jsonObject) {
            return jsonObject;
        }
        return new JSONArray();
    }


    /**
     * 信用卡逾期转换逾期对象
     */
    public static final Function<List<OverdueCreditCardAccount>, List<CreditReportSimpleCreditCardDO>> CREDIT_CARD_OVERDUE_CONVERT = simpleSaveReqVO -> {
        List<CreditReportSimpleCreditCardDO> simpleOverdueDOList = new ArrayList<>();
        simpleSaveReqVO.forEach(item -> {
            CreditReportSimpleCreditCardDO simpleOverdueDO = CreditReportSimpleCreditCardDO.builder()
                    .overdueType(2)
                    .openDate(item.getOpeningDate())
                    .accountStatus(item.getAccountStatus())
                    .accountCurrency(item.getAccountCurrency())
                    .institutionName(item.getInstitutionName())
                    .isOverdue(item.getCurrentOverdue())
                    .fiveYearsOverdue(item.getTotalOverdueMonthsFiveYears())
                    .numberDayOverdue(item.getOver90DaysOverdue())
                    .usedQuota(Optional.ofNullable(item.getCreditLimit()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(item.getBalance()).orElse(BigDecimal.ZERO)))
                    .balance(item.getBalance())
                    .totalAmount(item.getCreditLimit())
                    .build();
            simpleOverdueDOList.add(simpleOverdueDO);
        });
        return simpleOverdueDOList;
    };


    /**
     * 信用卡逾期转换未逾期对象
     */
    public static final Function<List<NonOverdueCreditCardAccount>, List<CreditReportSimpleCreditCardDO>> CREDIT_CARD_CONVERT = simpleSaveReqVO -> {
        List<CreditReportSimpleCreditCardDO> simpleOverdueDOList = new ArrayList<>();
        simpleSaveReqVO.forEach(item -> {
            CreditReportSimpleCreditCardDO simpleOverdueDO = CreditReportSimpleCreditCardDO.builder()
                    .overdueType(1)
                    .openDate(item.getOpeningDate())
                    .accountStatus(item.getAccountStatus())
                    .accountCurrency(item.getAccountCurrency())
                    .institutionName(item.getInstitutionName())
                    .usedQuota(item.getUsedLimit())
                    .balance(Optional.ofNullable(item.getCreditLimit()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(item.getUsedLimit()).orElse(BigDecimal.ZERO)))
                    .totalAmount(item.getCreditLimit())
                    .build();
            simpleOverdueDOList.add(simpleOverdueDO);
        });
        return simpleOverdueDOList;
    };

    /**
     * 贷款逾期转换逾期对象
     */
    public static final Function<List<OverdueAccount>, List<CreditReportSimpleLoanDO>> LOAN_OVERDUE_CONVERT = simpleSaveReqVO -> {
        List<CreditReportSimpleLoanDO> simpleOverdueDOList = new ArrayList<>();
        simpleSaveReqVO.forEach(item -> {
            CreditReportSimpleLoanDO simpleOverdueDO = CreditReportSimpleLoanDO.builder()
                    .overdueType(2)
                    .openDate(item.getOpenDate())
                    .businessTypes(item.getBusinessType())
                    .accountStatus(item.getAccountStatus())
                    .institutionName(item.getInstitutionName())
                    .fiveYearsOverdue(item.getTotalOverdueMonths())
                    .numberDayOverdue(item.getHasOverdue90dPlus())
                    .balance(item.getBalance())
                    .usedQuota(Optional.ofNullable(item.getLoanAmount()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(item.getBalance()).orElse(BigDecimal.ZERO)))
                    .totalAmount(item.getLoanAmount())
                    .isOverdue(item.getIsOverdue())
                    .build();
            simpleOverdueDOList.add(simpleOverdueDO);
        });
        return simpleOverdueDOList;
    };


    /**
     * 贷款逾期转换逾期对象
     */
    public static final Function<List<NeverOverdueLoanAccount>, List<CreditReportSimpleLoanDO>> LOAN_CONVERT = simpleSaveReqVO -> {
        List<CreditReportSimpleLoanDO> simpleOverdueDOList = new ArrayList<>();
        simpleSaveReqVO.forEach(item -> {
            CreditReportSimpleLoanDO simpleOverdueDO = CreditReportSimpleLoanDO.builder()
                    .overdueType(1)
                    .openDate(item.getOpenDate())
                    .businessTypes(item.getBusinessType())
                    .accountStatus(item.getAccountStatus())
                    .institutionName(item.getInstitutionName())
                    .balance(item.getBalance())
                    .usedQuota(Optional.ofNullable(item.getLoanAmount()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(item.getBalance()).orElse(BigDecimal.ZERO)))
                    .totalAmount(item.getLoanAmount())
                    .build();
            simpleOverdueDOList.add(simpleOverdueDO);
        });
        return simpleOverdueDOList;
    };

    /**
     * set 对象值方法
     *
     * @param simpleSaveReqVO 对象object
     * @param key             parenMap 中的key
     * @param parenObj        存对象属性的JSONObject
     * @param parser          字段类和转义方法类似  Integer::parseInt 将String 转成 Integer
     * @param setter          字段的set方法
     * @param <T>             泛型
     */
    public static <T> void accumulate(CreditReportSimpleSaveReqVO simpleSaveReqVO, String key, JSONObject parenObj,
                                      Function<String, T> parser, BiConsumer<CreditReportSimpleSaveReqVO, T> setter) {
        Object valueObj = parenObj.get(key);
        if (Objects.nonNull(valueObj)) {
            String valueStr = convertMoney(valueObj.toString());
            T value = parser.apply(valueStr);
            setter.accept(simpleSaveReqVO, value);
        }
    }

    /**
     * set 对象值方法 (值叠加)
     *
     * @param simpleSaveReqVO 对象object
     * @param value           值
     * @param setter          字段的set方法
     * @param <T>             泛型
     */
    @SuppressWarnings("unchecked")
    public static <T> void accumulateSup(CreditReportSimpleSaveReqVO simpleSaveReqVO, T value, Function<CreditReportSimpleSaveReqVO, T> getter, BiConsumer<CreditReportSimpleSaveReqVO, T> setter) {

            try {
                /*
                    getter  Function 函数带返回值 主要是提供获取对象属性值的方法 例：CreditReportSimpleSaveReqVO::getCreditLimitSum 提供一个get方法去获取参数
                 */
                T existingValue = getter.apply(simpleSaveReqVO);
                /*
                    当赋值的对象中值不存在 直接set值
                    setter：Function 函数带返回值 主要是提供set对象属性值的方法 例：CreditReportSimpleSaveReqVO::setCreditLimitSum 提供一个set方法去获取参数
                 */
                if (existingValue == null) {
                    setter.accept(simpleSaveReqVO, value);
                } else {
                   /*
                    当赋值的对象中值存在，则进行叠加操作
                    */
                    if (value instanceof Integer valueInteger && existingValue instanceof Integer existingValueInteger) {
                        existingValueInteger += valueInteger;
                        setter.accept(simpleSaveReqVO, (T) existingValueInteger);
                    } else if (value instanceof BigDecimal valueBigDecimal && existingValue instanceof BigDecimal existingValueBigDecimal) {
                        setter.accept(simpleSaveReqVO, (T) valueBigDecimal.add(existingValueBigDecimal));
                    } else {
                        // 如果类型不匹配，则抛出异常或者进行其他处理
                        log.error("简版征信报告：赋值类型不匹配类型转换异常");
                    }
                }
            } catch (NumberFormatException e) {
                log.info("赋值异常 value:{}",value);
            }
        }


    /**
     * 解析日期字符串，兼容多种格式
     * @param dateStr 日期字符串
     * @return LocalDate 对象，如果解析失败则返回 null
     */
    private static LocalDate parseDate(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            return null;
        }
        try {
            return LocalDate.parse(dateStr.trim(), DATE_FORMATTER);
        } catch (DateTimeParseException e) {
            log.warn("日期格式解析失败: '{}'", dateStr);
            return null;
        }
    }

    /**
     * 检查所有账户是否满足以下两个条件之一：
     * 1. 2年内开立的账户，其开立时间距报告时间 < 6个月。
     * 2. 2年外、5年内开立的账户，其账户状态为“结清”。
     *
     * @param allAccounts 包含所有账户（信用卡+贷款）的集合，元素需实现 AccountInfoProvider 接口
     * @param reportTimeStr 报告时间字符串
     * @return 如果所有账户都满足条件，返回 true；只要有一个不满足，就返回 false。
     */
    public static <T extends CreditCardAccount> boolean checkAccountOpeningDateAndStatus(
            Collection<T> allAccounts,
            String reportTimeStr) {

        if (allAccounts == null || allAccounts.isEmpty()) {
            return true; // 如果没有账户，可以认为条件满足
        }

        LocalDate reportDate = parseDate(reportTimeStr);
        if (reportDate == null) {
            log.error("报告时间格式无效，无法进行判断: '{}'", reportTimeStr);
            return false; // 报告时间无效，无法判断，视为不满足
        }

        for (T account : allAccounts) {
            String openDateStr = account.getOpenDate();
            LocalDate openDate = parseDate(openDateStr);

            if (openDate == null) {
                log.warn("账户开立日期为空或格式无效，跳过此账户: {}", account);
                continue; // 跳过日期无效的账户，或根据业务要求返回 false
            }

            // 计算报告日期和开立日期的年、月差距
            Period period = Period.between(openDate, reportDate);
            long totalMonthsBetween = ChronoUnit.MONTHS.between(openDate, reportDate);
            long yearsBetween = period.getYears();

            // === 开始核心逻辑判断 ===

            // 1️⃣ 判断是否在2年内
            if (yearsBetween < 2) {
                // 条件一：2年内的账户，开立时间距报告时间必须 < 6个月
                if (totalMonthsBetween >= 6) {
                    log.info("不是小白户: 账户(开立日期:{})在2年内，但开立距报告时间({})已超过6个月。", openDateStr, reportTimeStr);
                    return false; // 找到一个不满足条件的，立刻返回 false
                }
            }
            // 2️⃣ 判断是否在2年外、5年内
            else if (yearsBetween < 5) {
                // 条件二：2-5年内的账户，状态必须为“结清”
                String status = account.accountStatus();
                if (!STATUS_CLEARED.equals(status)) {
                    log.info("不是小白户: 账户(开立日期:{})在2-5年内，但账户状态({})不是'结清'。", openDateStr, status);
                    return false; // 找到一个不满足条件的，立刻返回 false
                }
            }
        }
        // 如果遍历完所有账户都没有找到不满足条件的，说明所有账户都通过了校验
        return true;
    }
    /**
     * 自动识别输入字符串的格式，并转换为 yyyy-MM-dd 格式输出
     *
     * @param dateStr 输入的日期字符串
     * @return 标准格式的字符串，如 "2025-05-07"
     */
    public static LocalDate parseAndFormatDate(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            return null;
        }

        dateStr = dateStr.trim();

        for (DateTimeFormatter formatter : INPUT_FORMATTERS) {
            try {
                String replaceAll = dateStr.replaceAll("\\D+", ".");
                String replace = replaceAll.replaceAll("^\\.|\\.$", "");
                LocalDate date = LocalDate.parse(replace, formatter);
                return LocalDate.parse(date.format(FORMATTER));
            } catch (DateTimeParseException ignored) {
                // 忽略异常，继续尝试下一个格式
            }
        }

        // 如果所有格式都不匹配
        log.info("简版征信无法解析日期: {}", dateStr);
        return null;
    }

    public static BiFunction<BigDecimal, BigDecimal, BigDecimal> ratio() {
        // 1. 定义一个 BiFunction 来计算百分比率
        return  (numerator, denominator) -> {
                    if (Objects.nonNull(numerator) && Objects.nonNull(denominator) && numerator.compareTo(BigDecimal.ZERO) > 0 && denominator.compareTo(BigDecimal.ZERO) > 0) {
                        return numerator.divide(denominator, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                    }else {
                        return BigDecimal.ZERO;
                    }
        };
    }

    /**
     * 信用卡判断统计
     * @param item 判断对象
     * @return 返回true / false
     */
    private static boolean accountStatus(CreditCardAccount item) {
        return StringUtils.isNotBlank(item.accountStatus()) && !item.accountStatus().contains("未激活") && !item.accountStatus().contains("销户");
    }

    /**
     * 贷记卡判断统计
     * @param item 判断对象
     * @return 返回true / false
     */
    private static boolean loanAccountStatus(CreditCardAccount item) {
        return StringUtils.isNotBlank(item.accountStatus()) && !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户");
    }

    /**
     * 统计大白户
     * @param item 判断对象
     * @return 返回true / false
     */
    private static boolean creditInvisible(CreditCardAccount item) {
        return StringUtils.isNotBlank(item.accountStatus()) && !item.accountStatus().contains("已结清");
    }

    /**
     * 贷记卡判断统计
     * @param item 判断对象
     * @return 返回true / false
     */
    private static boolean overdue90Account(CreditCardAccount item) {
        return StringUtils.isNotBlank(item.hasOverdue90dPlus()) && !Objects.equals(item.hasOverdue90dPlus(),"false");
    }


    /**
     *  住房按揭判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean loanHousingMortgage(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人住房商业贷款或者个⼈住房公积⾦贷款
        return StringUtils.isNotBlank(item.accountStatus()) && !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户")
                && StringUtils.isNotBlank(item.businessType()) && (item.businessType().contains(PERSONAL_HOUSING_LOAN) || item.businessType().contains(PERSONAL_COMMERCIAL_PROPERTY_LOAN));
    }

    /**
     *  汽车贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean loanAutomobile(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人汽车消费贷款
        return StringUtils.isNotBlank(item.accountStatus()) && !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户")
                && StringUtils.isNotBlank(item.businessType()) && item.businessType().contains(PERSONAL_AUTO_LOAN);
    }

    /**
     *  消费贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean consumerLoan(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人汽车消费贷款
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && item.businessType().contains(CONSUMER_LOAN);
    }

    /**
     *  经营性贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean operateLoan(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人汽车消费贷款
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && item.businessType().contains(OPERATE_LOAN);
    }


    /**
     *  小额贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean pettyLoan(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人汽车消费贷款
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && item.institutionName().contains(PETTY_LOAN);
    }



    /**
     *  消费金融贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean financeLoan(CreditCardAccount item) {
        // 未结清 并且 业务种类值包括 个人汽车消费贷款
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && item.institutionName().contains(FINANCE_LOAN);
    }

    /**
     * 银行贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean  loanBank(CreditCardAccount item) {
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && item.institutionName().contains(BANK);
    }

    /**
     * 非银行贷款判断条件
     * @param item 对象
     * @return 返回true / false
     */
    private static boolean  nonLoanBank(CreditCardAccount item) {
        return  StringUtils.isNotBlank(item.accountStatus()) && StringUtils.isNotBlank(item.businessType()) &&
                !item.accountStatus().contains("已结清") && !item.accountStatus().contains("销户") && !item.institutionName().contains(BANK);
    }


}
